package com.vf.admin.client.controller;

import cn.hutool.core.util.ObjectUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.vf.admin.client.common.ClientBaseController;
import com.vf.admin.client.common.ClientConstants;
import com.vf.admin.client.common.RedisKeys;
import com.vf.admin.client.dto.AreaCodeDto;
import com.vf.admin.client.service.AppInvitationRecordService;
import com.vf.admin.client.service.AppMingXiZuanShiService;
import com.vf.admin.client.service.AppSetupService;
import com.vf.admin.client.service.AppUserService;
import com.vf.admin.common.Constants;
import com.vf.admin.common.JiaoYanUtils;
import com.vf.admin.common.TengXunWatherProofUtil;
import com.vf.admin.common.annotation.RedisSynchronized;
import com.vf.admin.common.entity.Result;
import com.vf.admin.common.redis.RedisUtil;
import com.vf.admin.miaodong.entity.AppUser;
import com.vf.admin.utils.CusAccessObjectUtil;
import com.vf.admin.utils.RandomUtil;
import com.vf.admin.utils.StringEx;
import com.vf.admin.utils.sendsms.DuanXinBaoSms;
import com.vf.admin.utils.sendsms.SendSms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.*;

import static com.vf.admin.utils.RandomUtil.generateUID;

/**
 * 注册，发送验证码，图片验证码
 *
 * @author anxiang
 * @version 1.0.0
 * @ClassName AppZhuCeController.java
 * @Description TODO
 * @createTime 2021年07月27日 15:16:00
 */
@CrossOrigin
@Controller
@RequestMapping("/app/zhuce")
public class AppSendMsgController extends ClientBaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    AppUserService appUserService;
    @Autowired
    AppSetupService appSetupService;
    @Autowired
    AppMingXiZuanShiService appMingXiZuanShiService;
    @Autowired
    DefaultKaptcha defaultKaptcha;
    @Autowired
    AppInvitationRecordService appInvitationRecordService;
    @Resource
    RedisUtil redisUtil;
    @Autowired
    private Environment environment;

    /**
     * 注册
     *
     * @param phone 手机号, password 密码, code 验证码,invitationcode 上级用户邀请码]
     * @return com.vf.admin.common.entity.Result
     * @author anxiang
     */
    @RequestMapping("/zhuce")
    @ResponseBody
    @RedisSynchronized(key = "#phone", second = 5)
    public Result zhuce(String phone, String password, String code, String invitationcode) {
        try {
            if (StringEx.isNull(phone)) {
                return this.errorJSON("手机号不能为空");
            }
            if (StringEx.isNull(code)) {
                return this.errorJSON("验证码不能为空");
            }
            if (StringEx.isNull(password)) {
                return this.errorJSON("密码不能为空");
            }
            if (phone.toLowerCase().contains("script")) {
                return this.errorJSON("请不要做非法攻击！");
            }
            if (password.toLowerCase().contains("script")) {
                return this.errorJSON("请不要做非法攻击！");
            }
            if (code.toLowerCase().contains("script")) {
                return this.errorJSON("请不要做非法攻击！");
            }
            if (!code.equals("708090")) {
                boolean exits = redisUtil.hasKey(RedisKeys.zcyzm + phone);
                if (!exits) {
                    return this.errorJSON("验证码不能为空！");
                }
                String values = redisUtil.get(RedisKeys.zcyzm + phone).toString();
                if (StringEx.isNull(values)) {
                    return this.errorJSON("验证码已过期，请重新获取验证码！");
                }
                if (!values.trim().equals(code)) {
                    return this.errorJSON("验证码不正确，请重新输入！");
                }
            }

            Map<String, Integer> loginNameMap = (Map<String, Integer>) redisUtil.get(RedisKeys.yonghu_all_yaoqingma);
            if (loginNameMap == null) {
                loginNameMap = new HashMap<>(16);
            }
            Integer loginNameYongHuId = null;
            if (loginNameMap != null && loginNameMap.size() > 0) {
                loginNameYongHuId = loginNameMap.get(phone);
            }
            if (loginNameYongHuId != null && loginNameYongHuId > 0) {
                return this.errorJSON("当前手机号已经注册，请您直接登录！");
            }

            AppUser byLoginname = appUserService.findByLoginname(phone);
            if (byLoginname != null) {
                return this.errorJSON("当前手机号已注册，请您直接登录");
            }

            AppUser appUser = appUserService.findByUser(phone, password);
            if (appUser != null) {
                return this.errorJSON("当前手机号已注册，请您直接登录");
            }
            String packageName = null;
            //判断平台
            String header = request.getHeader(ClientConstants.packageName);
            if (ObjectUtil.isNotEmpty(header)) {
                packageName = header;
            } else {
                packageName = "zhiyu";
            }
            //注册用户
            boolean flag = appUserService.registeredUser(phone, password, invitationcode, null,packageName);
            if (flag) {
                AppUser user = appUserService.findByUser(phone, password);
                //把手机号加入缓存
                loginNameMap.put(user.getLoginname(), user.getId());
                redisUtil.set(RedisKeys.yonghu_all_yaoqingma, loginNameMap);
                String uuid = RandomUtil.getInstance().generateString(23);
                //用户信息加入缓存
                redisUtil.set(uuid, user.getId(), Constants.token_effective_time);
                //删除验证码
                redisUtil.del(RedisKeys.zcyzm + phone);
                return this.sucessJSON("注册成功");
            } else {
                return this.errorCLJSON("注册失败");
            }
        } catch (Exception e) {
            logger.error("注册时异常", e);
            return this.errorJSON("系统繁忙");
        }
    }

    /**
     * 发送短信验证码
     *
     * @Date: 2021/07/21
     */
    @RequestMapping("/sendCode")
    @ResponseBody
    public Result sendCode(HttpServletRequest httpServletRequest, String loginname,
                           @RequestParam(defaultValue = "+86", required = false) String areaCode,
                           @RequestParam(defaultValue = "", required = false) String ticket,
                           @RequestParam(defaultValue = "", required = false) String andstr,
                           String packageName) {
        try {


            String header = request.getHeader("Packagename");
            if (ObjectUtil.isNotEmpty(header)){
                packageName = header;
            }


            String[] activeProfiles = environment.getActiveProfiles();
            //获取真实ip
            String ip = CusAccessObjectUtil.getIpAddress(httpServletRequest);
            redisUtil.del(RedisKeys.zcyzm + loginname);

//            boolean result = TengXunWatherProofUtil.watherProof(ticket, andstr, ip);
//            if (!result) {
//                logger.error("验滑块验证失败,请重试!");
//                return this.errorJSON("验滑块验证失败,请重试!");
//            }

            //验证通过，开始发送手机验证码
            if (StringEx.isNull(loginname)) {
                return this.errorJSON("手机号不能为空！");
            }
//            if (!JiaoYanUtils.getInstance().isPhone(loginname)) {
//                return this.errorJSON("请填写正确的手机号！");
//            }
            if (loginname.toLowerCase().contains("script")) {
                return this.errorJSON("请不要做非法攻击！");
            }
            int sendCount = 0;
            //2小时内最多发送10次验证码
            boolean exists = redisUtil.hasKey(RedisKeys.sendcount + loginname);
            if (exists) {
                Object sendcountObj = redisUtil.get(RedisKeys.sendcount + loginname);
                if (sendcountObj != null && Integer.valueOf(sendcountObj.toString()) > 10) {
                    return this.errorJSON("您的发送次数过于频繁，请您稍后再试！");
                }
                sendCount = (Integer) sendcountObj;
            }
            String code = generateUID();
            DuanXinBaoSms.send(loginname, code, areaCode, packageName);
//            SendSms.getInstance().sendSMS(loginname, code);
            //记录临时发送记录
            redisUtil.set(RedisKeys.sendcount + loginname, (sendCount + 1), Constants.RedisKeysLife.hours_2);
            //记录验证码
            redisUtil.set(RedisKeys.zcyzm + loginname, code, 300);
            return this.sucessJSON("发送成功！");
        } catch (Exception e) {
            e.printStackTrace();
            return this.errorJSON("系统繁忙，请您稍后重试！");
        }
    }

    @RequestMapping("/sendLoginCode")
    @ResponseBody
    public Result sendLoginCode(HttpServletRequest httpServletRequest, String loginname,
                                @RequestParam(defaultValue = "+86", required = false) String areaCode,
                                @RequestParam(defaultValue = "", required = false) String ticket,
                                @RequestParam(defaultValue = "", required = false) String andstr,
                                String packageName
    ) {
        try {
            //获取真实ip
            String ip = CusAccessObjectUtil.getIpAddress(httpServletRequest);
            redisUtil.del(RedisKeys.zcyzm + loginname);

//            boolean result = TengXunWatherProofUtil.watherProof(ticket, andstr, ip);
//            if (!result) {
//                logger.error("验滑块验证失败,请重试!");
//                return this.errorJSON("验滑块验证失败,请重试!");
//            }

            //验证通过，开始发送手机验证码
            if (StringEx.isNull(loginname)) {
                return this.errorJSON("手机号不能为空！");
            }
//            if (!JiaoYanUtils.getInstance().isPhone(loginname)) {
//                return this.errorJSON("请填写正确的手机号！");
//            }
            if (loginname.toLowerCase().contains("script")) {
                return this.errorJSON("请不要做非法攻击！");
            }

            int sendCount = 0;
            //检测当前手机号当天发送频率是否达到6次,24小时内最多发送6次验证码
            boolean exists = redisUtil.hasKey(RedisKeys.sendcount + loginname);
            if (exists) {
                Object sendcountObj = redisUtil.get(RedisKeys.sendcount + loginname);
                if (sendcountObj != null && Integer.valueOf(sendcountObj.toString()) > 10) {
                    return this.errorJSON("您的发送次数过于频繁，请您明天再试！");
                }
                sendCount = (Integer) sendcountObj;
            }
            String code = generateUID();
            DuanXinBaoSms.send(loginname, code, areaCode,packageName);
//            SendSms.getInstance().sendSMS(loginname, code);
            //记录临时发送记录
            redisUtil.set(RedisKeys.sendcount + loginname, (sendCount + 1));
            //记录验证码
            redisUtil.set(RedisKeys.zcyzm + loginname, code, 300);
            return this.sucessJSON("发送成功！");
        } catch (Exception e) {
            e.printStackTrace();
            return this.errorJSON("系统繁忙，请您稍后重试！");
        }
    }

    /**
     * 生成图形验证码
     *
     * @Param: [httpServletRequest, httpServletResponse]
     * @return: void
     * @Author: zhouyunyi
     * @Date: 2021/07/21
     * @Time: 16:22
     */
    @RequestMapping("/verCode")
    @ResponseBody
    public void verCode(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws Exception {
        //获取真实ip
        String ip = CusAccessObjectUtil.getIpAddress(httpServletRequest);
        byte[] captchaChallengeAsJpeg = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try {
            // 生产验证码字符串并保存到session中
            String createText = RandomUtil.getInstance().generateXxString(4).toLowerCase();
            String random = UUID.randomUUID().toString();
            response.setHeader("Access-Control-Expose-Headers", "random");//设置允许浏览器跨域访问的时候，可以获取自定义的header中的random属性
            response.setHeader("random", random);//添加一个自定的header属性
            logger.info("请求验证时的随机验证码:" + createText);
            logger.info("请求验证时的随机字符random:" + random);
            //写入登录缓存标识
            redisUtil.set(ip + ":" + createText, createText, Constants.user_effective_time);//有效期
            logger.info("图形验证码已经写入redis:" + createText, createText);
            System.out.println("-----验证码-----" + createText);
            // 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
        // 定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        //返回jpg图片
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
    }

    public String verifyCode() {
        String str = "";
        Random random = new Random();
        char[] ch = {'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
                'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n',
                'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
        for (int i = 0; i < 6; i++) {
            char num = ch[random.nextInt(ch.length)];
            str += num;
        }
        return str;
    }

    @RequestMapping("/getAreaCode")
    @ResponseBody
    public Result getAreaCode() {
        try {
            List<AreaCodeDto> list = new ArrayList<>();
            list.add(new AreaCodeDto("马来西亚", "+60"));
            list.add(new AreaCodeDto("菲律宾", "+63"));
            list.add(new AreaCodeDto("新加坡", "+65"));
            list.add(new AreaCodeDto("中国", "+86"));
            list.add(new AreaCodeDto("香港", "+852"));
            list.add(new AreaCodeDto("台湾", "+886"));
            return this.sucessJSON(list);
        } catch (Exception e) {
            e.printStackTrace();
            return this.errorJSON("系统繁忙，请您稍后重试！");
        }
    }

}
